package com.kinghunt.misp.service.impl.userx;

import com.kinghunt.misp.common.constant.OrganizationConstant;
import com.kinghunt.misp.common.dto.common.Tree;
import com.kinghunt.misp.common.dto.userx.OrganizationDTO;
import com.kinghunt.misp.common.dto.userx.RoleDTO;
import com.kinghunt.misp.dal.dao.userx.OrganizationDAO;
import com.kinghunt.misp.dal.dao.userx.OrganizationRoleDAO;
import com.kinghunt.misp.dal.dao.userx.RoleDAO;
import com.kinghunt.misp.dal.model.userx.OrganizationDO;
import com.kinghunt.misp.dal.model.userx.RoleDO;
import com.kinghunt.misp.service.api.userx.OrganizationReadService;
import com.bygoodtech.kings.base.utils.ConvertUtil;
import com.bygoodtech.kings.common.dto.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 机构
 * @Author jiangtao
 * @Date 2023/7/5 21:55
 */
@Slf4j
@Service
public class OrganizationReadServiceImpl implements OrganizationReadService {
    @Autowired(required = false)
    OrganizationDAO organizationDAO;
    @Autowired(required = false)
    OrganizationRoleDAO organizationRoleDAO;
    @Autowired(required = false)
    RoleDAO roleDAO;

    @Override
    public ApiResult<OrganizationDTO> getOrganizationById(Long id) {
        OrganizationDO organizationDO = organizationDAO.selectByPrimaryKey(id);
        OrganizationDTO dto = ConvertUtil.convert(organizationDO, OrganizationDTO.class);

        List<Long> roleIds = organizationRoleDAO.selectRoleIdsByOrgId(id);
        if (! CollectionUtils.isEmpty(roleIds)) {
            List<RoleDO> roleDOS = roleDAO.selectByIds(roleIds);
            List<RoleDTO> roleDTOs = ConvertUtil.convert(roleDOS, RoleDTO.class);
            dto.setRoles(roleDTOs);
        }

        return ApiResult.ok(dto);
    }

    @Override
    public ApiResult<Tree<OrganizationDTO>> getOrganizationTree(String appCode) {
        Tree<OrganizationDTO> tree = null;
        Map<Long, List<OrganizationDTO>> organizationMap = getAllOrganizationParentIdMap(appCode);
        if (CollectionUtils.isEmpty(organizationMap)) {
            return ApiResult.ok();
        }

        OrganizationDTO currentNode = organizationMap.get(OrganizationConstant.ORGANIZATION_ANCESTOR_PARENT_ID).get(0);
        tree = processTree(currentNode, organizationMap);
        return ApiResult.ok(tree);
    }

    /**
     * 获取应用下所有机构的 {parentId - 机构} map
     *
     * @param appCode 应用code
     * @return 机构map
     */
    private Map<Long, List<OrganizationDTO>> getAllOrganizationParentIdMap(String appCode) {
        List<OrganizationDO> organizationDOS = organizationDAO.selectByAppCode(appCode);
        if (CollectionUtils.isEmpty(organizationDOS)) {
            return Collections.EMPTY_MAP;
        }
        List<OrganizationDTO> organizationDTOs = ConvertUtil.convert(organizationDOS, OrganizationDTO.class);
        return organizationDTOs.stream().collect(Collectors.groupingBy(OrganizationDTO::getParentId));
    }

    /**
     * 递归处理机构树
     *
     * @param currentNode 当前节点
     * @param organizationMap 机构Map
     * @return 机构树
     */
    private Tree<OrganizationDTO> processTree(OrganizationDTO currentNode, final Map<Long, List<OrganizationDTO>> organizationMap) {
        if (Objects.isNull(currentNode)) {
            return null;
        }

        Tree<OrganizationDTO> tree = new Tree<>();
        tree.setCurrentNode(currentNode);
        List<OrganizationDTO> children = Optional.ofNullable(organizationMap.get(currentNode.getId())).orElse(Collections.EMPTY_LIST);
        List<Tree<OrganizationDTO>> childrenTree = new ArrayList<>();
        for (OrganizationDTO c : children) {
            childrenTree.add(processTree(c, organizationMap));
        }
        tree.setChildren(childrenTree);

        return tree;
    }
}
